from ConfigParser import ConfigParser, RawConfigParser

import os

import Tool,Axis

#####################################################################

class MachineType:
    (Lathe, ThreeAxisMill, FourAxisMill) = range(3)

def getMachineType(typeStr):
    if typeStr == "lathe": return MachineType.Lathe
    elif typeStr == "threeaxismill": return MachineType.ThreeAxisMill
    elif typeStr == "fouraxismill": return MachineType.FourAxisMill

def getMachineTypeStr(machineType):
    if machineType == MachineType.Lathe: return "lathe"
    elif machineType == MachineType.ThreeAxisMill: return "threeaxismill"
    elif machineType == MachineType.FourAxisMill: return "fouraxismill"

def getMachineTypeAxises(machineType):
    if machineType == MachineType.Lathe:
        return ['x', 'y']
    elif machineType == MachineType.ThreeAxisMill:
        return ['x', 'y', 'z']
    elif machineType == MachineType.FourAxisMill:
        return ['x', 'y', 'z', 'r']

#####################################################################

class UnitType:
    (Metric, Imperial) = range(2)

def getUnitType(unitTypeStr):
    if unitTypeStr == "metric": return UnitType.Metric
    elif unitTypeStr == "imperial": return UnitType.Imperial

def getUnitTypeStr(unitType):
    if unitType == UnitType.Metric: return "metric"
    elif unitType == UnitType.Imperial: return "imperial"

#####################################################################



#####################################################################

class Location:
    (Left,Right,Front,Back,Center) = range(5)

def getLocation(locationStr):
    if locationStr == "left": return Location.Left
    elif locationStr == "right": return Location.Right
    elif locationStr == "front": return Location.Front
    elif locationStr == "back": return Location.Back
    elif locationStr == "center": return Location.Center

def getLocationStr(location):
    if location == Location.Left: return "left"
    elif location == Location.Right: return "right"
    elif location == Location.Front: return "front"
    elif location == Location.Back: return "back"
    elif location == Location.Center: return "center"

#####################################################################

currentMachine = None

def setCurrentMachine(machine):
    global currentMachine
    currentMachine = machine

def getCurrentMachine():
    global currentMachine
    return currentMachine

class Machine:
    def __init__(self):
        self.name = "Default"
        self.machineType = -1
        self.maxRpm = 0
        self.unitType = -1
        self.axises = {}
        self.tools = {}

    def getType(self): return self.machineType
    def setType(self, machineType):
        axises = getMachineTypeAxises(machineType)

        self.machineType = machineType

        for axis in axises:
            if not axis in self.axises:
                if axis == 'r':
                    self.addAxis(axis, Axis.RotaryAxis(100, -100, 100, 'c', Location.Left, 0, 0, 0))
                else:
                    self.addAxis(axis, Axis.LinearAxis(100, -100, 100))

    def getUnitType(self): return self.unitType
    def setUnitType(self, unitType): self.unitType = unitType

    def getMaxRpm(self): return self.maxRpm
    def setMaxRpm(self, maxRpm): self.maxRpm = maxRpm

    def getName(self): return self.name
    def setName(self, name): self.name = name

    def addAxis(self, axisName, axis):
        if not axisName in self.axises:
            self.axises[axisName] = axis

    def getAxis(self, axisName):
        if axisName in self.axises: return self.axises[axisName]

    def addTool(self, tool, toolIndex = -1):
        if toolIndex == -1:
            toolIndex = self.getNextFreeToolIndex()
            tool.setToolIndex(toolIndex)

        self.tools[toolIndex] = tool

        print "Next Free Tool Index: " + str(self.getNextFreeToolIndex())

    def removeTool(self, tool):
        if tool.getToolIndex() in self.tools:
            self.tools.pop(tool.getToolIndex())

    def getTool(self, toolName):
        for index, tool in self.tools.iteritems():
            if tool.getName() == toolName:
                return tool
        
    def getTools(self):
        return self.tools

    def getNextFreeToolIndex(self):
        toolIndex = 0

        while True:
            if not toolIndex in self.tools:
                return toolIndex

            toolIndex += 1


    def printToStream(self):
        print "Machine: " + self.name
        print "Type: " + getMachineTypeStr(self.machineType)
        print "Units: " + getUnitTypeStr(self.unitType)
        print "MaxRpm: " + str(self.maxRpm)

        for axis in getMachineTypeAxises(self.machineType):
            print "Axis: " + axis
            print "\tMaxVelocity: " + str(self.axises[axis].maxVelocity)
            print "\tMinTravel: " + str(self.axises[axis].minTravel)
            print "\tMaxTravel: " + str(self.axises[axis].maxTravel)

            if axis == 'r':
                print "\tAssignment: " + self.axises[axis].assignment
                print "\tLocation: " + getLocationStr(self.axises[axis].location)
                print "\tPosX: " + str(self.axises[axis].xpos)
                print "\tPosY: " + str(self.axises[axis].ypos)
                print "\tPosZ: " + str(self.axises[axis].zpos)

        for index, tool in self.tools.iteritems():
            print "Tool: " + tool.getName()
            print "\tMaterial: " + Tool.getToolMaterialStr(tool.getMaterial())
            print "\tType: " + Tool.getToolTypeStr(tool.getToolType())
            print "\tIndex: " + str(tool.getToolIndex())

            if tool.getToolType() == Tool.ToolType.LatheTool:
                print "\tCutterType: " + str(tool.getCutterType())
                print "\tOrientation: " + str(tool.getOrientation())
                print "\tFront Angle: " + str(tool.getFrontAngle())
                print "\tBack Angle: " + str(tool.getBackAngle())
                print "\tTool Angle: " + str(tool.getToolAngle())
                print "\tTip Radius: " + str(tool.getTipRadius())
            else:
                print "\tCutter Type: " + str(tool.getCutterType())
                print "\tDiameter: " + str(tool.getDiameter())
                print "\tLength Offset: " + str(tool.getLengthOffset())
                print "\tCutting Length: " + str(tool.getCuttingLength())
                print "\tCutting Angle: " + str(tool.getCuttingAngle())
                print "\tHelix Angle: " + str(tool.getHelixAngle())
                print "\tCorner Radius: " + str(tool.getCornerRadius())
                print "\tFlat Radius: " + str(tool.getFlatRadius())
                print "\tFlutes: " + str(tool.getFlutes())
                print "\tCenter Cutting: " + str(tool.getCenterCutting())

        print "Next Free Tool Index: " + str(self.getNextFreeToolIndex())

def loadMachineConfiguration(configFile):
    config = ConfigParser()

    if os.path.exists(configFile):
        config.readfp(open(configFile))
    else:
        raise Exception("Path does not exist: (" + configFile + ")")

    name = config.get("machine", "name")
    machineType = config.get("machine", "type")
    unitType = config.get("machine", "units")
    maxRpm = config.getint("machine", "maxrpm")
	
    machine = Machine()

    machine.setName(name)
    machine.setType(getMachineType(machineType))
    machine.setUnitType(getUnitType(unitType))
    machine.setMaxRpm(maxRpm)

    # Load the axis sections
    axises = getMachineTypeAxises(machine.getType())
    
    for axisName in axises:
        axis = machine.getAxis(axisName)

        print "Adding axis: " + axisName
        section = "axis_" + axisName
        maxVelocity = config.getint(section, "maxvelocity")
        maxTravel = config.getint(section, "maxtravel")
        minTravel = config.getint(section, "mintravel")

        axis.setMaxVelocity(maxVelocity)
        axis.setMinTravel(minTravel)
        axis.setMaxTravel(maxTravel)

        if axisName == 'r':
            assignment = config.get(section, "assignment")
            location = config.get(section, "location")
            posx = config.getint(section, "posx")
            posy = config.getint(section, "posy")
            posz = config.getint(section, "posz")

            axis.setAssignment(assignment)
            axis.setLocation(getLocation(location))
            axis.setPosition(posx, posy, posz)

    toolIndex = 0

    while toolIndex < 99:
        section = "tool_" + str(toolIndex)

        if config.has_section(section):
            print "loading tool: " + section
            toolName = config.get(section, "name")
            toolType = Tool.getToolType(config.get(section, "tooltype"))
            toolMaterial = Tool.getToolMaterial(config.get(section, "material"))

            tool = None

            if toolType == Tool.ToolType.LatheTool:
                tool = Tool.LatheTool()
                tool.setCutterType(config.getint(section, "cuttertype"))
                tool.setOrientation(config.getint(section, "orientation"))
                tool.setFrontAngle(config.getfloat(section, "frontangle"))
                tool.setBackAngle(config.getfloat(section, "backangle"))
                tool.setToolAngle(config.getfloat(section, "toolangle"))
                tool.setTipRadius(config.getfloat(section, "tipradius"))
            elif toolType == Tool.ToolType.MillingTool:
                tool = Tool.MillingTool()
                tool.setCutterType(config.getint(section, "cuttertype"))
                tool.setDiameter(config.getfloat(section, "diameter"))
                tool.setLengthOffset(config.getfloat(section, "lengthoffset"))
                tool.setCuttingLength(config.getfloat(section, "cuttinglength"))
                tool.setCuttingAngle(config.getfloat(section, "cuttingangle"))
                tool.setHelixAngle(config.getfloat(section, "helixangle"))
                tool.setCornerRadius(config.getfloat(section, "cornerradius"))
                tool.setFlatRadius(config.getfloat(section, "flatradius"))
                tool.setFlutes(config.getint(section, "flutes"))
                tool.setCenterCutting(config.getboolean(section, "centercutting"))

            tool.setName(toolName)
            tool.setToolType(toolType)
            tool.setMaterial(toolMaterial)
            tool.setToolIndex(toolIndex)

            machine.addTool(tool, toolIndex)

        toolIndex += 1
    return machine


def saveMachineConfiguration(configFile, machine):
    config = RawConfigParser()

    config.add_section("machine")
    config.set("machine", "name", machine.getName())
    config.set("machine", "type", getMachineTypeStr(machine.getType()))
    config.set("machine", "units", getUnitTypeStr(machine.getUnitType()))
    config.set("machine", "maxrpm", machine.getMaxRpm())

    axises = getMachineTypeAxises(machine.getType())

    for axisName in axises:
        section = "axis_" + axisName
        axis = machine.getAxis(axisName)
        if axis == None:
            continue

        config.add_section(section)
        config.set(section, "maxvelocity", axis.getMaxVelocity())
        config.set(section, "mintravel", axis.getMinTravel())
        config.set(section, "maxtravel", axis.getMaxTravel())

        if axisName == 'r':
            config.set(section, "assignment", axis.getAssignment())
            config.set(section, "location", getLocationStr(axis.getLocation()))
            position = axis.getPosition()

            config.set(section, "posx", position[0])
            config.set(section, "posy", position[1])
            config.set(section, "posz", position[2])

    for key, tool in machine.tools.iteritems():
        section = "tool_" + str(tool.getToolIndex())
        config.set(section, "name", tool.getName())
        config.set(section, "tooltype", Tool.getToolTypeStr(tool.getToolType()))
        config.set(section, "material", Tool.getToolMaterialStr(tool.getMaterial()))
        config.set(section, "cuttertype", tool.getCutterType())

        if tool.getToolType() == Tool.ToolType.LatheTool:
            config.set(section, "orientation", tool.getOrientation())
            config.set(section, "frontangle", tool.getFrontAngle())
            config.set(section, "backangle", tool.getBackAngle())
            config.set(section, "toolangle", tool.getToolAngle())
            config.set(section, "tipradius", tool.getTipRadius())
        else:
            config.set(section, "diameter", tool.getDiameter())
            config.set(section, "lengthoffset", tool.getLengthOffset())
            config.set(section, "cuttinglength", tool.getCuttingLength())
            config.set(section, "cuttingangle", tool.getCuttingAngle())
            config.set(section, "helixangle", tool.getHelixAngle())
            config.set(section, "cornerradius", tool.getCornerRadius())
            config.set(section, "flatradius", tool.getFlatRadius())
            config.set(section, "flutes", tool.getFlutes())
            config.set(section, "centercutting", tool.getCenterCutting())

    config.write(open(configFile, "wb"))


